package com.dimples.dd.auth.config;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.dimples.dd.auth.core.model.SysUserDetails;
import com.dimples.dd.common.constant.JwtClaimConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;

import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * JWT 自定义字段配置
 *
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2024/6/13
 */
@Configuration
public class JwtTokenCustomizerConfig {

    /**
     * JWT 自定义字段
     *
     * @see <a href="https://docs.spring.io/spring-authorization-server/reference/guides/how-to-custom-claims-authorities.html">Add custom claims to JWT access tokens</a>
     */
    @Bean
    public OAuth2TokenCustomizer<JwtEncodingContext> oAuth2TokenCustomizer() {
        return context -> {
            if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType()) && context.getPrincipal() instanceof UsernamePasswordAuthenticationToken) {
                // Customize headers/claims for access_token
                Optional.ofNullable(context.getPrincipal().getPrincipal()).ifPresent(principal -> {
                    JwtClaimsSet.Builder claims = context.getClaims();
                    if (principal instanceof SysUserDetails user) { // 系统用户添加自定义字段
                        claims.claim(JwtClaimConstants.USER_ID, ObjectUtil.isNotEmpty(user.getUserId()) ? user.getUserId() : -1);
                        claims.claim(JwtClaimConstants.USERNAME, StrUtil.isNotBlank(user.getUsername()) ? user.getUsername() : StrUtil.EMPTY);
                        claims.claim(JwtClaimConstants.DEPT_ID, ObjectUtil.isNotEmpty(user.getDeptId()) ? user.getDeptId() : -1);
                        claims.claim(JwtClaimConstants.DATA_SCOPE, ObjectUtil.isNotEmpty(user.getDataScope()) ? user.getDataScope() : -1);

                        // 获取申请的scopes
                        Set<String> scopes = context.getAuthorizedScopes();
                        // 获取用户的权限
                        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

                        // 提取权限并转为字符串
                        Set<String> authoritySet = Optional.ofNullable(authorities).orElse(Collections.emptyList()).stream()
                                // 获取权限字符串
                                .map(GrantedAuthority::getAuthority)
                                // 去重
                                .collect(Collectors.toSet());
                        // 合并scope与用户信息
                        authoritySet.addAll(scopes);

                        claims.claim(JwtClaimConstants.AUTHORITIES, authoritySet);
                    }
                });
            }
        };
    }

}
